<?php
/**
 * 微信PHP-SDK，用于开发单用户版微信公众号管理系统
 * 服务器端必须要有 CURL 支持
 * 2014年3月
 * @author 、小陈叔叔 <cjango@163.com>
 * http://git.oschina.net/cjango/cjango-sdk
 */
namespace Common\ORG;

class Wechat {
	/* 获取ACCESS_TOKEN URL */
	const AUTH_URL                = 'https://api.weixin.qq.com/cgi-bin/token';
	/* 菜单相关URL */
	const MENU_CREATE_URL         = 'https://api.weixin.qq.com/cgi-bin/menu/create';
	const MENU_GET_URL            = 'https://api.weixin.qq.com/cgi-bin/menu/get';
	const MENU_DELETE_URL         = 'https://api.weixin.qq.com/cgi-bin/menu/delete';
	/* 用户及用户分组URL */
	const USER_GET_URL            = 'https://api.weixin.qq.com/cgi-bin/user/get';
	const USER_INFO_URL           = 'https://api.weixin.qq.com/cgi-bin/user/info';
	const USER_IN_GROUP           = 'https://api.weixin.qq.com/cgi-bin/groups/getid';
	const GROUP_GET_URL           = 'https://api.weixin.qq.com/cgi-bin/groups/get';
	const GROUP_CREATE_URL        = 'https://api.weixin.qq.com/cgi-bin/groups/create';
	const GROUP_UPDATE_URL        = 'https://api.weixin.qq.com/cgi-bin/groups/update';
	const GROUP_MEMBER_UPDATE_URL = 'https://api.weixin.qq.com/cgi-bin/groups/members/update';
	/* 发送客服消息URL */
	const CUSTOM_SEND_URL         = 'https://api.weixin.qq.com/cgi-bin/message/custom/send';
	/* 二维码生成 URL*/
	const QRCODE_URL              = 'https://api.weixin.qq.com/cgi-bin/qrcode/create';
	const QRCODE_SHOW_URL         = 'https://mp.weixin.qq.com/cgi-bin/showqrcode';
	/* OAuth2.0授权地址 */
	const OAUTH_AUTHORIZE_URL     = 'https://open.weixin.qq.com/connect/oauth2/authorize';
	const OAUTH_USER_TOKEN_URL    = 'https://api.weixin.qq.com/sns/oauth2/access_token';
	
	private $token;
	private $appid;
	private $secret;
	private $access_token;
	private $user_token;
	private $debug = false;
	private $data  = array();
	private $send  = array();
	private $error = NULL;
	private $ticket;

	function __construct($options = array()) {
		$this->token = isset($options['token']) ? $options['token'] : '';
		$this->appid = isset($options['appid']) ? $options['appid'] : '';
		$this->secret = isset($options['secret']) ? $options['secret'] : '';
		$this->access_token = isset($options['access_token']) ? $options['access_token'] : '';
		$this->debug = isset($options['debug']) ? $options['debug'] : false;
	}

	/**
	 * 验证URL有效性
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function valid() {
		$echoStr = $_GET["echostr"];
		if (isset($echoStr)) {
			$this->checkSignature() && exit($echoStr);
		}else {
			!$this->checkSignature() && exit('Access Denied!');
		}
		return true;
	}

	/**
	 * 检查用户签名信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function checkSignature() {
		//如果调试状态，直接返回真
		if ($this->debug) return true;
		$signature = $_GET['signature'];
		$timestamp = $_GET['timestamp'];
		$nonce     = $_GET['nonce'];
		if (empty($signature) || empty($timestamp) || empty($nonce)) {
			return false;
		}
		$token = $this->token;
		if (!$token) return false;
		$tmpArr = array($token, $timestamp, $nonce);
		sort($tmpArr, SORT_STRING);
		$tmpStr = implode($tmpArr);
		return sha1($tmpStr) == $signature;
	}

	/**
	 * 取得 access_token
	 * @return string|boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function getToken() {
		$access_token = $this->access_token;
		if (!empty($access_token)) {
			return $this->access_token;
		}else {
			if ($this->getAccessToken()) {
				return $this->access_token;
			}else {
				return false;
			}
		}
	}
	
	/**
	 * 从远端接口获取ACCESS_TOKEN
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function getAccessToken() {
		$params = array(
				'grant_type'=> 'client_credential',
				'appid'    => $this->appid,
				'secret'=> $this->secret
		);
		$jsonStr = $this->http(self::AUTH_URL, $params);
		if ($jsonStr) {
			$jsonArr = $this->parseJson($jsonStr);
			if ($jsonArr) {
				return $this->access_token = $jsonArr['access_token'];
			}else {
				return false;
			}
		}else {
			return false;
		}
	}

	/**
	 * 获取自定义菜单
	 * @return array|boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function menus() {
		$params = array(
				'access_token' => $this->access_token
		);
		$jsonStr = $this->http(self::MENU_GET_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return $jsonArr['menu'];
		}else {
			return false;
		}
	}

	/**
	 * 创建自定义菜单
	 * @param  array $menus 自定义菜单数组
	 * @return boolen
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function menu_create($menus = array()) {
		if (empty($menus)) {
			$this->error = '菜单内容必须要填写';
			return false;
		}
		//创建菜单之前，执行删除操作
		//$this->menu_delete();
		$params = $this->json_encode($menus);
		$url    = self::MENU_CREATE_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}

	/**
	 * 删除自定义菜单
	 * @return boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function menu_delete() {
		$params = array(
				'access_token' => $this->access_token
		);
		$jsonStr = $this->http(self::MENU_DELETE_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}

	/**
	 * 从远端获取用户分组
	 * @return array|boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function groups() {
		$params = array(
				'access_token' => $this->access_token,
		);
		$jsonStr = $this->http(self::GROUP_GET_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return $jsonArr['groups'];
		}else {
			return false;
		}
	}
	
	/**
	 * 添加用户分组
	 * @param string $name 分组名称
	 * @return boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function group_add($name = '') {
		if (empty($name)) {
			$this->error = '请输入一个分组名称';
			return false;
		}
		$params = array(
				'group' => array(
						'name' => $name
				)
		);
		$params = $this->json_encode($params);
		$url    = self::GROUP_CREATE_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}
	
	/**
	 * 修改分组名
	 * @param integer $gid 分组编号
	 * @param string $name 分组名称
	 * @return boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function group_edit($gid = '', $name = '') {
		if (empty($name) || empty($gid)) {
			$this->error = '请选择一个分组，并输入一个新的名称';
			return false;
		}
		$params = array(
				'group' => array(
						'id'   => $gid,
						'name' => $name
				)
		);
		$params = $this->json_encode($params);
		$url    = self::GROUP_UPDATE_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}
	
	/**
	 * 获取关注者列表 
	 * @param  sting $next_openid 第一个拉取的OPENID，不填默认从头开始拉取
	 * @return array|boolean 返回用户信息的一个数组
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function users($next_openid = '') {
		$this->getToken();
		!empty($next_openid) && $params['next_openid'] = $next_openid;
		$params['access_token'] = $this->access_token;
		
		$jsonStr = $this->http(self::USER_GET_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			//优化了返回数组的结构
			$openId = $jsonArr['data']['openid'];
			unset($jsonArr['data']);
			$jsonArr['openid'] = $openId;
			return $jsonArr;
		}else {
			return false;
		}
	}

	/**
	 * 获取用户基本信息
	 * @param string $openid 用户的OPENID
	 * @return array|boolean 返回用户信息的一个数组
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function user($openid = '') {
		if (empty($openid)) {
			$this->error = '请输入一个用户的OpenID';
			return false;
		}
		$params = array(
				'access_token' => $this->access_token,
				'lang'         => 'zh_CN',
				'openid'       => $openid
		);
		$jsonStr = $this->http(self::USER_INFO_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		unset($jsonArr['subscribe']);
		if ($jsonArr) {
			return $jsonArr;
		}else {
			return false;
		}
	}

	/**
	 * 查询用户所在分组
	 * @return integer|boolean 用户所在分组ID
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function user_in_group($openid = '') {
		if (empty($openid)) {
			$this->error = '请输入一个用户的OpenID';
			return false;
		}
		$params = array(
				'openid' => $openid
		);
		$params = json_encode($params);
		$url    = self::USER_IN_GROUP . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return $jsonArr['groupid'];
		}else {
			return false;
		}
	}

	/**
	 * 移动用户分组
	 * @param string $openid 用户OPENID
	 * @param integer $gid 移动到的分组编号
	 * @return boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function user_to_group($openid = '', $gid = '') {
		if (empty($openid) || empty($gid)) {
			$this->error = '请选择一个用户，并指定一个新的分组';
			return false;
		}
		$params = array(
				'openid' => $openid,
				'to_groupid' => $gid
		);
		$params = json_encode($params);
		$url    = self::GROUP_MEMBER_UPDATE_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}

	/**
	 * 获取微信推送的数据,将键值全部转换为小写后返回
	 * @return array 转换为数组后的数据
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	public function request(){
		$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
		if (!empty($postStr)) {
			$data = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
			return $this->data = array_change_key_case($data, CASE_LOWER);
		}else {
			return false;
		}
	}
	
	/**
	 * * 被动响应微信发送的信息（自动回复）
	 * @param  string $to      接收用户名
	 * @param  string $from    发送者用户名
	 * @param  array  $content 回复信息，文本信息为string类型
	 * @param  string $type    消息类型
	 * @param  string $flag    是否新标刚接受到的信息
	 * @return string          XML字符串
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	public function response($content, $type = 'text', $flag = 0){
		/* 基础数据 */
		$this->data = array(
				'ToUserName'   => $this->data['fromusername'],
				'FromUserName' => $this->data['tousername'],
				'CreateTime'   => time(),
				'MsgType'      => $type,
		);
	
		/* 添加类型数据 */
		$this->$type($content);
	
		/* 添加状态 */
		$this->data['FuncFlag'] = $flag;
	
		/* 转换数据为XML */
		$xml = new \SimpleXMLElement('<xml></xml>');
		$this->data2xml($xml, $this->data);
		exit($xml->asXML());
	}
	
	/**
	 * 回复文本信息
	 * @param  string $content 要回复的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function text($content){
		$this->data['Content'] = $content;
	}
	
	/**
	 * 回复音乐信息
	 * @param  string $content 要回复的音乐
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function music($music){
		list(
				$music['Title'],
				$music['Description'],
				$music['MusicUrl'],
				$music['HQMusicUrl']
		) = $music;
		$this->data['Music'] = $music;
	}
	
	/**
	 * 回复图文信息
	 * @param  string $news 要回复的图文内容
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function news($news){
		$articles = array();
		foreach ($news as $key => $value) {
			list(
					$articles[$key]['Title'],
					$articles[$key]['Description'],
					$articles[$key]['PicUrl'],
					$articles[$key]['Url']
			) = $value;
			if($key >= 9) { break; } //最多只允许10调新闻
		}
		$this->data['ArticleCount'] = count($articles);
		$this->data['Articles'] = $articles;
	}
	
	/**
	 * 数据XML编码
	 * @param  object $xml  XML对象
	 * @param  mixed  $data 数据
	 * @param  string $item 数字索引时的节点名称
	 * @return string xml
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function data2xml($xml, $data, $item = 'item') {
		foreach ($data as $key => $value) {
			/* 指定默认的数字key */
			is_numeric($key) && $key = $item;
			/* 添加子元素 */
			if(is_array($value) || is_object($value)){
				$child = $xml->addChild($key);
				$this->data2xml($child, $value, $item);
			} else {
				if(is_numeric($value)){
					$child = $xml->addChild($key, $value);
				} else {
					$child = $xml->addChild($key);
					$node  = dom_import_simplexml($child);
					$node->appendChild($node->ownerDocument->createCDATASection($value));
				}
			}
		}
	}

	/**
	 * 发送客服消息
	 * @return boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function sendMsg($openid, $content, $msgtype = 'text') {
		/* 基础数据 */
		$this->send ['touser'] = $openid;
		$this->send ['msgtype'] = $msgtype;
		/* 添加类型数据 */
		$sendtype = 'send' . $msgtype;
		$this->$sendtype($content);
		/* 发送 */
		$params = self::json_encode($this->send);
		$url    = self::CUSTOM_SEND_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return true;
		}else {
			return false;
		}
	}

	/**
	 * 发送文本消息
	 * @param string $content 要发送的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendtext($content) {
		$this->send['text'] = array(
				'content' => $content
		);
	}

	/**
	 * 发送图片消息
	 * @param string $content 要发送的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendimage($content) {
		$this->send['image'] = array(
				'media_id' => $content
		);
	}

	/**
	 * 发送视频消息
	 * @param  string $content 要发送的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendvideo($video){
		list (
			$video ['media_id'],
			$video ['title'],
			$video ['description']
		) = $video;
		
		$this->send ['video'] = $video;
	}
	
	/**
	 * 发送语音消息
	 * @param string $content 要发送的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendvoice($content) {
		$this->send['voice'] = array(
				'media_id' => $content
		);
	}
	
	/**
	 * 发送音乐消息
	 * @param string $content 要发送的信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendmusic($music) {
		list ( 
			$music['title'], 
			$music['description'], 
			$music['musicurl'], 
			$music['hqmusicurl'], 
			$music['thumb_media_id']
		) = $music;
		$this->send['music'] = $music;
	}
	
	/**
	 * 发送图文消息
	 * @param  string $news 要回复的图文内容
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function sendnews($news){
		$articles = array();
		foreach ($news as $key => $value) {
			list(
				$articles[$key]['title'],
				$articles[$key]['description'],
				$articles[$key]['url'],
				$articles[$key]['picurl']
			) = $value;
			if($key >= 9) { break; } //最多只允许10条图文信息
		}
		$this->send['articles'] = $articles;
	}
	
	/**
	 * OAuth 授权跳转接口
	 * @param string $callback 回调URI，填写完整地址，带http://
	 * @param sting $state 重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值
	 * @param string snsapi_userinfo获取用户授权信息，snsapi_base直接返回openid
	 * @return string
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	public function getOAuthRedirect($callback, $state='', $scope='snsapi_userinfo'){
		return self::OAUTH_AUTHORIZE_URL.'appid='.$this->appid.'&redirect_uri='.urlencode($callback).'&response_type=code&scope='.$scope.'&state='.$state.'#wechat_redirect';
	}
	
	/**
	 * 通过code获取Access Token
	 * @return array|boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	public function getOauthAccessToken(){
		$code = isset($_GET['code']) ? $_GET['code'] : '';
		if (!$code) return false;
		$params = array(
				'appid' => $this->appid,
				'secret'=> $this->secret,
				'code'  => $code,
				'grant_type' => 'authorization_code'
		);
		$jsonStr = $this->http(self::OAUTH_USER_TOKEN_URL, $params);
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return $jsonArr;
		}else {
			return false;
		}
	}
	
	/**
	 * 获取二维码图像地址
	 * @param  integer $scene_id 场景值 1-100000整数
	 * @param  boolean $limit    true永久二维码 false 临时
	 * @param  integer $expire   临时二维码有效时间
	 * @return string|boolean    二维码图片地址
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function getQRUrl($scene_id = '', $limit = true, $expire = 1800) {
		if (!isset($this->ticket)) {
			if (!$this->qrcode($scene_id, $limit, $expire)) return false;
		}
		return self::QRCODE_SHOW_URL.'?ticket=' . $this->ticket;
	}

	/**
	 * 生成推广二维码
	 * @param  integer $scene_id 场景值 1-100000整数
	 * @param  boolean $limit    true永久二维码 false 临时
	 * @param  integer $expire   临时二维码有效时间
	 * @return string|boolean
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function qrcode($scene_id = '', $limit = true, $expire = 1800) {
		if (empty($scene_id) || !is_numeric($scene_id) || $scene_id > 100000 || $scene_id < 1) {
			$this->error = '场景值必须是1-100000之间的整数';
			return false;
		}
		$params['action_name'] = $limit?'QR_LIMIT_SCENE':'QR_SCENE';
		if (!$limit) $params['expire_seconds'] = $expire;
		$params['action_info'] = array('scene' => array('scene_id' => $scene_id));
		$params = json_encode($params);
		$url = self::QRCODE_URL . '?access_token=' . $this->access_token;
		$jsonStr = $this->http($url, $params, 'POST');
		$jsonArr = $this->parseJson($jsonStr);
		if ($jsonArr) {
			return $this->ticket = $jsonArr['ticket'];
		}else {
			return false;
		}
	}
	
	/**
	 * 不转义中文字符和\/的 json 编码方法
	 * @param  array $array
	 * @return json
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private static function json_encode($array = array()) {
		$array = str_replace("\\/", "/", json_encode($array));
		$search = '#\\\u([0-9a-f]+)#ie';
		if (strpos(strtoupper(PHP_OS), 'WIN' ) === false) {
			$replace = "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))";//LINUX
		} else {
			$replace = "iconv('UCS-2', 'UTF-8', pack('H4', '\\1'))";//WINDOWS
		}
		return preg_replace($search, $replace, $array );
	}

	/**
	 * 解析JSON编码，如果有错误，则返回错误并设置错误信息
	 * @param json $json json数据
	 * @return array
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function parseJson($json) {
		$jsonArr = json_decode($json, true);
		if (isset($jsonArr['errcode'])) {
			if ($jsonArr['errcode'] == 0) return true;
			$this->error = $this->ErrorCode($jsonArr['errcode']);
			return false;
		}else {
			return $jsonArr;
		}
	}

	/**
	 * 发送HTTP请求方法，目前只支持CURL发送请求
	 * @param  string $url    请求URL
	 * @param  array  $params 请求参数
	 * @param  string $method 请求方法GET/POST
	 * @return array  $data   响应数据
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function http($url, $params = array(), $method = 'GET'){
		$opts = array(
				CURLOPT_TIMEOUT        => 30,
				CURLOPT_RETURNTRANSFER => 1,
				CURLOPT_SSL_VERIFYPEER => false,
				CURLOPT_SSL_VERIFYHOST => false
		);
		/* 根据请求类型设置特定参数 */
		switch(strtoupper($method)){
			case 'GET':
				$opts[CURLOPT_URL] = $url .'?'. http_build_query($params);
				break;
			case 'POST':
				$opts[CURLOPT_URL] = $url;
				$opts[CURLOPT_POST] = 1;
				$opts[CURLOPT_POSTFIELDS] = $params;
				break;
		}
		/* 初始化并执行curl请求 */
		$ch = curl_init();
		curl_setopt_array($ch, $opts);
		$data  = curl_exec($ch);
		$err = curl_errno($ch);
		$errmsg = curl_error($ch);
		curl_close($ch);
		if ($err > 0) {
			$this->error = $errmsg;
			return false;
		}else {
			return $data;
		}
	}
	
	/**
	 * 捕获错误信息
	 * @return string 中文错误信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	function getError() {
		return $this->error;
	}

	/**
	 * 获取全局返回错误码
	 * @param integer $code 错误码
	 * @return string 错误信息
	 * @author 、小陈叔叔 <cjango@163.com>
	 */
	private function ErrorCode($code) {
		switch ($code) {
			case -1    : return '系统繁忙 '; break;
			case 40001 : return '获取access_token时AppSecret错误，或者access_token无效 '; break;
			case 40002 : return '不合法的凭证类型'; break;
			case 40003 : return '不合法的OpenID '; break;
			case 40004 : return '不合法的媒体文件类型'; break;
			case 40005 : return '不合法的文件类型'; break;
			case 40006 : return '不合法的文件大小'; break;
			case 40007 : return '不合法的媒体文件id '; break;
			case 40008 : return '不合法的消息类型 '; break;
			case 40009 : return '不合法的图片文件大小'; break;
			case 40010 : return '不合法的语音文件大小'; break;
			case 40011 : return '不合法的视频文件大小'; break;
			case 40012 : return '不合法的缩略图文件大小'; break;
			case 40013 : return '不合法的APPID'; break;
			case 40014 : return '不合法的access_token '; break;
			case 40015 : return '不合法的菜单类型 '; break;
			case 40016 : return '不合法的按钮个数 '; break;
			case 40017 : return '不合法的按钮个数'; break;
			case 40018 : return '不合法的按钮名字长度'; break;
			case 40019 : return '不合法的按钮KEY长度 '; break;
			case 40020 : return '不合法的按钮URL长度 '; break;
			case 40021 : return '不合法的菜单版本号'; break;
			case 40022 : return '不合法的子菜单级数'; break;
			case 40023 : return '不合法的子菜单按钮个数'; break;
			case 40024 : return '不合法的子菜单按钮类型'; break;
			case 40025 : return '不合法的子菜单按钮名字长度'; break;
			case 40026 : return '不合法的子菜单按钮KEY长度 '; break;
			case 40027 : return '不合法的子菜单按钮URL长度 '; break;
			case 40028 : return '不合法的自定义菜单使用用户'; break;
			case 40029 : return '不合法的oauth_code'; break;
			case 40030 : return '不合法的refresh_token'; break;
			case 40031 : return '不合法的openid列表 '; break;
			case 40032 : return '不合法的openid列表长度 '; break;
			case 40033 : return '不合法的请求字符，不能包含\uxxxx格式的字符 '; break;
			case 40035 : return '不合法的参数'; break;
			case 40038 : return '不合法的请求格式'; break;
			case 40039 : return '不合法的URL长度 '; break;
			case 40050 : return '不合法的分组id'; break;
			case 40051 : return '分组名字不合法'; break;
			case 41001 : return '缺少access_token参数'; break;
			case 41002 : return '缺少appid参数'; break;
			case 41003 : return '缺少refresh_token参数'; break;
			case 41004 : return '缺少secret参数'; break;
			case 41005 : return '缺少多媒体文件数据'; break;
			case 41006 : return '缺少media_id参数'; break;
			case 41007 : return '缺少子菜单数据'; break;
			case 41008 : return '缺少oauth code'; break;
			case 41009 : return '缺少openid'; break;
			case 42001 : return 'access_token超时'; break;
			case 42002 : return 'refresh_token超时'; break;
			case 42003 : return 'oauth_code超时'; break;
			case 43001 : return '需要GET请求'; break;
			case 43002 : return '需要POST请求'; break;
			case 43003 : return '需要HTTPS请求'; break;
			case 43004 : return '需要接收者关注'; break;
			case 43005 : return '需要好友关系'; break;
			case 44001 : return '多媒体文件为空'; break;
			case 44002 : return 'POST的数据包为空'; break;
			case 44003 : return '图文消息内容为空'; break;
			case 44004 : return '文本消息内容为空'; break;
			case 45001 : return '多媒体文件大小超过限制'; break;
			case 45002 : return '消息内容超过限制'; break;
			case 45003 : return '标题字段超过限制'; break;
			case 45004 : return '描述字段超过限制'; break;
			case 45005 : return '链接字段超过限制'; break;
			case 45006 : return '图片链接字段超过限制'; break;
			case 45007 : return '语音播放时间超过限制'; break;
			case 45008 : return '图文消息超过限制'; break;
			case 45009 : return '接口调用超过限制'; break;
			case 45010 : return '创建菜单个数超过限制'; break;
			case 45015 : return '回复时间超过限制'; break;
			case 45016 : return '系统分组，不允许修改'; break;
			case 45017 : return '分组名字过长'; break;
			case 45018 : return '分组数量超过上限'; break;
			case 46001 : return '不存在媒体数据'; break;
			case 46002 : return '不存在的菜单版本'; break;
			case 46003 : return '不存在的菜单数据'; break;
			case 46004 : return '不存在的用户'; break;
			case 47001 : return '解析JSON/XML内容错误'; break;
			case 48001 : return 'api功能未授权'; break;
			case 50001 : return '用户未授权该api'; break;
			default    : return '未知错误';
		}
	}
}